package com.product.magina.dingtalk.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.magina.common.constant.ProjectConst;
import com.magina.common.exception.BusinessException;
import com.magina.common.model.DTJsSignatureModel;
import com.magina.common.utils.DingTalkUtil;
import com.product.magina.dingtalk.service.DingTalkService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.client.RestTemplate;

import javax.servlet.http.HttpServletRequest;
import java.util.Map;
import java.util.concurrent.TimeUnit;

@Slf4j
@Service(value = "dingTalkService")
@Transactional(rollbackFor = Exception.class)
public class DingTalkServiceImpl implements DingTalkService {

    @Autowired
    private RestTemplate restTemplate;
//    @Autowired
//    private RedisCacheService redisCacheService;

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    // 调整到1小时50分钟(官方建议2h)
    public static final long cacheTime = 1000 * 60 * 110;

    @Value(value = "${dingTalk.corpid}")
    private String corpId;

    @Value(value="${dingTalk.corpsecret}")
    private String corpSecret;

    @Value("${dingTalk.agentid}")
    private String agentId;

    @Value("${dingTalk.noncestr}")
    private String nonceStr;

    @Value("${dingTalk.appkey}")
    private String appkey;

    @Value("${dingTalk.appsercret}")
    private String appsercret;

    @Value("${dingTalk.signatureurl}")
    private String signatureurl;

    @Override
    public DTJsSignatureModel getConfig(HttpServletRequest request) throws BusinessException {
        /*
         *以http://localhost/test.do?a=b&c=d为例
         *request.getRequestURL的结果是http://localhost/test.do
         *request.getQueryString的返回值是a=b&c=d
         */
//        String urlString = request.getRequestURL().toString();
//        String queryString = request.getQueryString();
//        String url = null;
//        if (queryString != null) {
//            url = urlString + queryString;
//        } else {
//            url = urlString;
//        }
//        String signedUrl = url;
        String signedUrl = signatureurl+"/";
        long timeStamp = System.currentTimeMillis() / 1000;     //时间戳参数
        String accessToken = null;                              //token参数
        String ticket = null;                                   //ticket参数
        String signature = null;                                //签名参数
        try {
            accessToken=getAccessToken(appkey  ,appsercret,ProjectConst.ACCESS_APP_TOKEN_URL);
            ticket=getTicket(accessToken);
            signature=DingTalkUtil.sign(ticket,nonceStr,timeStamp,signedUrl);
//            String signature1=DingTalkUtil.getSign(ticket,nonceStr,timeStamp,signedUrl);
//            System.out.println(signature1);
            log.info(signature);

        } catch (Exception e) {
            throw new BusinessException(e.getMessage());
        }
        String str = "{jsticket:'" + ticket + "',signature:'" + signature + "',nonceStr:'" + nonceStr + "',timeStamp:'"
                + timeStamp + "',corpId:'" + corpId + "',agentId:'" + agentId+ "'}";
        log.info("url:"+signedUrl);
        log.info(str);
        DTJsSignatureModel model = new DTJsSignatureModel();
        model.setAgentId(agentId);
        model.setCorpId(corpId);
        model.setJsticket(ticket);
        model.setNonceStr(nonceStr);
        model.setTimeStamp(timeStamp);
        model.setSignature(signature);
        return model;
    }

    @Override
    public JSONObject getDingTalkUserInfo(String code) throws BusinessException {
        String accessToken= this.getAccessToken(appkey,appsercret,ProjectConst.ACCESS_APP_TOKEN_URL);
        String userId  = getUserInfo(accessToken,code);
        JSONObject userInfo = getUser(accessToken,userId);
        log.info(userInfo.toJSONString());
//        DingTalkClient client = new DefaultDingTalkClient("https://oapi.dingtalk.com/topapi/attendance/listschedule");
//        OapiAttendanceListscheduleRequest request = new OapiAttendanceListscheduleRequest();
//        request.setWorkDate(new Date());
//        request.setOffset(0L);
//        request.setSize(100L);
//        OapiAttendanceListscheduleResponse execute = client.execute(request,accessToken);
        return userInfo;
    }

    private String getAccessToken(String key,String secret,String initUrl) throws BusinessException {
        String accessToken = stringRedisTemplate.opsForValue().get(key);
        if(StringUtils.isEmpty(accessToken)){
            log.info("token无缓存,重新获取!");
            String url = initUrl.replace("ID", key).replace("SECRECT", secret);
            Map<String, Object> getAccessTokenResult = restTemplate.getForObject(url, Map.class);
            if(ObjectUtils.isEmpty(getAccessTokenResult)){
                throw new BusinessException("请求异常");
            }
            if(0!=(int)(getAccessTokenResult.get("errcode"))){
                throw new BusinessException(getAccessTokenResult.get("errmsg").toString());
            }
             accessToken = getAccessTokenResult.get("access_token").toString();
            stringRedisTemplate.opsForValue().set(key,accessToken,cacheTime,TimeUnit.MILLISECONDS);
        }
        return accessToken;
    }


    private String getTicket( String accessToken) throws BusinessException {
        String ticket = stringRedisTemplate.opsForValue().get(accessToken);
        if(StringUtils.isEmpty(ticket)){
            log.info("ticket无缓存,重新获取!");
            String url = ProjectConst.TICKET_URL.replace("ACCESS_TOKEN", accessToken);
            Map<String, Object> result = restTemplate.getForObject(url, Map.class);
            if(ObjectUtils.isEmpty(result)){
                throw new BusinessException("请求异常");
            }
            if(0!=(int)(result.get("errcode"))){
                throw new BusinessException(result.get("errmsg").toString());
            }
             ticket = result.get("ticket").toString();
            stringRedisTemplate.opsForValue().set(accessToken,ticket,cacheTime,TimeUnit.MILLISECONDS);
        }
        return ticket;
    }

    /**
     *
     * @param accessToken
     * @param userId
     * @return 返回值
     *  {
     *     "errcode": 0,
     *     "errmsg": "ok",
     *     "name": "test1",
     *     "unionid": "PiiiPyQqBNBii0HnCJ3zljcuAiEiE",
     *     "userid": "zhangsan",
     *     "isLeaderInDepts": "{1:false}",
     *     "isBoss": false,
     *     "hiredDate": 1520265600000,
     *     "isSenior": false,
     *     "department": [1,2],
     *     "orderInDepts": "{1:71738366882504}",
     *     "active": false,
     *     "avatar": "dingtalk.com/abc.jpg",
     *     "isAdmin": false,
     *     "isHide": false,
     *     "jobnumber": "001",
     *     "position": "manager"
     * }
     * @throws BusinessException
     */
    private JSONObject getUser(String accessToken, String userId) throws BusinessException {
        String url = ProjectConst.USER_URL.replace("ACCESS_TOKEN", accessToken).replace("USERID",userId);
        JSONObject result = restTemplate.getForObject(url, JSONObject.class);
        if(ObjectUtils.isEmpty(result)){
            throw new BusinessException("请求异常");
        }
        if(0!=(int)(result.get("errcode"))){
            throw new BusinessException(result.get("errmsg").toString(),result.get("errcode").toString());
        }
        return result;
    }

    /**
     *
     * @param accessToken
     * @param code
     * @return 返回值
     * {
     *     "userid": "****",
     *     "sys_level": 1,
     *     "errmsg": "ok",
     *     "is_sys": true,
     *     "deviceId": "***",
     *     "errcode": 0
     * }
     * @throws BusinessException
     */
    private String getUserInfo( String accessToken,String code) throws BusinessException {
        String url = ProjectConst.USER_INFO_URL.replace("ACCESS_TOKEN", accessToken).replace("CODE",code);
        Map<String, Object> result = restTemplate.getForObject(url, Map.class);
        if(ObjectUtils.isEmpty(result)){
            throw new BusinessException("请求异常");
        }
        if(0!=(int)(result.get("errcode"))){
            throw new BusinessException(result.get("errmsg").toString());
        }
        String userId = result.get("userid").toString();
        return userId;
    }
}
